package models;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Page;
import play.data.validation.Constraints;
import play.db.ebean.Model;

/**
 * Modele de la classe Utilisateur.
 * 
 * @author ProjetSI-QCM
 */
@SuppressWarnings("serial")
@Entity
public class Utilisateur extends Model {
    /**
     * Identifiant du Utilisateur.
     */
    @Id
    private Long idUtilisateur;
    /**
     * Statut de l'utilisateur (Expert, Etudiant, Administrateur).
     */
    @Enumerated(EnumType.STRING)
    private Statut statut;
    /**
     * Numero Etudiant (Uniquement si Statut = Etudiant).
     */
    private String numetudiant;

    /**
     * Login du Utilisateur.
     */
    @Constraints.Required
    private String login;

    /**
     * Mot de passe (chiffrage avec java.security).
     */
    @Constraints.Required
    private String password;
    /**
     * Nom de l'utilisateur.
     */
    private String nom;
    /**
     * Prenom de l'utilisateur.
     */
    private String prenom;
    /**
     * Email de l'utilisateur.
     */
    @Constraints.Email
    private String email;

    /**
     * Liste des QCM passés par l'utilisateur.
     */
    private List<UtilisateurQcm> listeQcmPasses = new ArrayList<UtilisateurQcm>();
    /**
     * Liste des QCM créés par l'utilisateur (Enseignant/Admin uniquement).
     */
    private List<Qcm> listeQcmCrees = new ArrayList<Qcm>();

    /**
     * Finder de la classe Utilisateur.
     */
    private static Finder<Long, Utilisateur> find = new Finder<Long, Utilisateur>(Long.class,
            Utilisateur.class);

    /**
     * La méthode permet de retrouver un utilisateur à partir de son ID.
     * 
     * @param id
     *            Identifiant de l'utilisateur
     * @return Utilisateur
     */
    public static Utilisateur findById(final Long id) {
        return Ebean.find(Utilisateur.class, id);
    }

    /**
     * Permet de trouver tous les Utilisateurs pour un Statut donné.
     * 
     * @param statut
     *            Le statut recherché.
     * @return List<Utilisateur> La liste des Utilisateur de ce Statut.
     */
    public static List<Utilisateur> findByStatut(final Statut statut) {
        return find.where().eq("statut", statut.name()).findList();
    }

    /**
     * Permet d'authentifier un utilisateur à partir de son login et password.
     * 
     * @param log
     *            Login saisi
     * @param pwd
     *            Password saisi
     * @return L'objet Utilisateur si login/mdp bon.
     */
    public static Utilisateur authenticate(final String log, final String pwd) {
        return find.where().eq("login", log)
                .eq("password", controllers.Utile.generateMD5(pwd))
                .findUnique();
    }

    /**
     * Recupère tous les Utilisateurs.
     * 
     * @return List<Utilisateur> La liste des Utilisateurs.
     */
    public static List<Utilisateur> findAll() {
        return find.all();
    }

    /**
     * Permet de sauvegarder un Utilisateur en Base de Données.
     * 
     * @param us
     *            l'objet à sauvegarder.
     */
    public static void create(final Utilisateur us) {
        us.save();
    }

    /**
     * Permet de modifier un Utilisateur en Base de Données.
     * 
     * @param us
     *            L'objet à modifier.
     */
    public static void update(final Utilisateur us) {
        us.update();
    }

    /**
     * Permet de Supprimer un Utilisateur de la base de données.
     * 
     * @param id
     *            L'identifiant de l'Utilisateur à supprimer.
     */
    public static void delete(final Long id) {
        find.ref(id).delete();
    }

	/**
	 * Génère les Options pour une liste déroulante.
	 * 
	 * @return Map<String,String> la liste des users sans les étudiants.
	 */
	public static Map<String, String> options() {
		final LinkedHashMap<String, String> options = 
				new LinkedHashMap<String, String>();
		for (Utilisateur c : Utilisateur.find.orderBy("idUtilisateur").findList()) {
			if (!c.getStatut().equals(Statut.Etudiant)) {
				options.put(c.getIdUtilisateur().toString(),
						c.getNom() + " " + c.getPrenom());
			}
		}
		return options;
	}
    
    /**
     * Génère les Options pour une liste déroulante.
     * 
     * @return Map<String,String> la liste de tous les users.
     */
    public static Map<String, String> options2() {
        final LinkedHashMap<String, String> options2 = 
                new LinkedHashMap<String, String>();
        for (Utilisateur c : Utilisateur.find.orderBy("idUtilisateur").findList()) {
        	options2.put(c.getIdUtilisateur().toString(),
                    c.getNom() + " " + c.getPrenom());
        }
        return options2;
    }

	/**
	 * Retourne une Page de Utilisateur.
	 * 
	 * @param page
	 *            Page à afficher
	 * @param pageSize
	 *            Nombre d'objets par page
	 * @param sortBy
	 *            Propriété utilisée pour le tri
	 * @param order
	 *            Sens du tri (asc ou desc)
	 * @param filter
	 *            Filtre appliqué sur le nom de la colonne
	 * @return Page<Utilisateur> la page
	 */
	public static Page<Utilisateur> page(final int page, final int pageSize,
			final String sortBy, final String order, final String filter) {
		return find.where().ilike("idUtilisateur", "%" + filter + "%")
				.orderBy(sortBy + " " + order)
				.findPagingList(pageSize).setFetchAhead(false).getPage(page);
	}

	/**
	 * @return the idUtilisateur
	 */
	public final Long getIdUtilisateur() {
		return idUtilisateur;
	}

	/**
	 * @param id the idUtilisateur to set
	 */
	public final void setIdUtilisateur(final Long id) {
		this.idUtilisateur = id;
	}

	/**
	 * @return the statut
	 */
	public final Statut getStatut() {
		return statut;
	}

	/**
	 * @param s the statut to set
	 */
	public final void setStatut(final Statut s) {
		this.statut = s;
	}

	/**
	 * @return the numetudiant
	 */
	public final String getNumetudiant() {
		return numetudiant;
	}

	/**
	 * @param num the numetudiant to set
	 */
	public final void setNumetudiant(final String num) {
		this.numetudiant = num;
	}

	/**
	 * @return the login
	 */
	public final String getLogin() {
		return login;
	}

	/**
	 * @param l the login to set
	 */
	public final void setLogin(final String l) {
		this.login = l;
	}

	/**
	 * @return the password
	 */
	public final String getPassword() {
		return password;
	}

	/**
	 * @param psw the password to set
	 */
	public final void setPassword(final String psw) {
		this.password = psw;
	}

	/**
	 * @return the nom
	 */
	public final String getNom() {
		return nom;
	}

	/**
	 * @param n the nom to set
	 */
	public final void setNom(final String n) {
		this.nom = n;
	}

	/**
	 * @return the prenom
	 */
	public final String getPrenom() {
		return prenom;
	}

	/**
	 * @param p the prenom to set
	 */
	public final void setPrenom(final String p) {
		this.prenom = p;
	}

	/**
	 * @return the email
	 */
	public final String getEmail() {
		return email;
	}

	/**
	 * @param e the email to set
	 */
	public final void setEmail(final String e) {
		this.email = e;
	}

	/**
	 * @return the listeQcmPasses
	 */
	@OneToMany(mappedBy = "utilisateur", cascade = CascadeType.ALL)
	public final List<UtilisateurQcm> getListeQcmPasses() {
		return listeQcmPasses;
	}

	/**
	 * @param l the listeQcmPasses to set
	 */
	public final void setListeQcmPasses(final List<UtilisateurQcm> l) {
		this.listeQcmPasses = l;
	}

	/**
	 * @return the listeQcmCrees
	 */
	@OneToMany(mappedBy = "utilisateur", cascade = CascadeType.ALL)
	public final List<Qcm> getListeQcmCrees() {
		return listeQcmCrees;
	}

	/**
	 * @param l the listeQcmCrees to set
	 */
	public final void setListeQcmCrees(final List<Qcm> l) {
		this.listeQcmCrees = l;
	}

}
